import { app, ipcMain, session } from 'electron'
import axios from 'axios'
import path from 'path'
import fs from 'fs'
import setCookie from 'set-cookie-parser'
import dayjs from 'dayjs'

import type { IpcMainInvokeEvent } from 'electron'
import type { AxiosRequestConfig } from 'axios'

async function customAxios(_: IpcMainInvokeEvent, config: AxiosRequestConfig) {
  const response = await axios.request(config)
  const { data, headers } = response
  return { data, headers }
}

async function downloadFile(config: FileBufferParams) {
  const response = await axios.get(config.url, {
    responseType: 'arraybuffer',
    headers: {
      'User-Agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
      Referer: config.referer || 'https://www.bilibili.com/'
    }
  })
  return Buffer.from(response.data)
}

async function getUrlFileBuffer(_: IpcMainInvokeEvent, config: FileBufferParams) {
  if (config.cache) {
    const userDataPath = app.getPath('userData')
    const cacheFilePath = path.join(userDataPath, config.cache.folder, config.cache.name)
    if (!fs.existsSync(cacheFilePath)) {
      // 路径中有文件夹不存在就去创建
      fs.mkdirSync(path.dirname(cacheFilePath), { recursive: true })
    }
    const buffer = await downloadFile(config)
    fs.writeFile(cacheFilePath, buffer, () => {})
    return buffer
  }

  const buffer = await downloadFile(config)
  return buffer
}

function getCacheFileBuffer(_: IpcMainInvokeEvent, cache: NonNullable<FileBufferParams['cache']>) {
  const userDataPath = app.getPath('userData')
  const cacheFilePath = path.join(userDataPath, cache.folder, cache.name)
  if (fs.existsSync(cacheFilePath)) {
    const buffer = fs.readFileSync(cacheFilePath)
    return buffer
  }
  return null
}

// 拦截所有请求
function updateRequestHeaders() {
  session.defaultSession.webRequest.onBeforeSendHeaders(async (details, callback) => {
    const { requestHeaders } = details
    try {
      // 解决请求资源返回403问题
      const parsedURL = new URL(details.url)
      let customOrigin = parsedURL.origin
      // 解决bili视频资源必须传Referer，且值必须为 https://www.bilibili.com
      if (['.bilivideo.', '.bilibili.'].some((reg) => customOrigin.includes(reg))) {
        customOrigin = 'https://www.bilibili.com'
      }
      const customAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/130.0.0.0 Safari/537.36'
      requestHeaders['User-Agent'] = customAgent
      requestHeaders['Origin'] = customOrigin
      requestHeaders['Referer'] = customOrigin

      // 设置cookies
      const cookies = await session.defaultSession.cookies.get({ url: details.url })
      if (cookies.length > 0) {
        const cookieString = cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ')
        details.requestHeaders['Cookie'] = cookieString
      }

      callback({ cancel: false, requestHeaders })
    } catch (e) {
      console.error(e)
      callback({ cancel: true })
    }
  })

  session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
    const { responseHeaders } = details

    // 允许所有来源，解决跨域
    responseHeaders!['access-control-allow-origin'] = ['*']

    // 储存cookie
    const cookies = responseHeaders!['set-cookie']
    if (Array.isArray(cookies)) {
      const cookiesParse = setCookie.parse(cookies)
      cookiesParse.forEach((item) => {
        session.defaultSession.cookies.set({
          ...item,
          url: details.url,
          sameSite: 'strict',
          expirationDate: dayjs(item.expires).unix()
        })
      })
    }

    callback({ responseHeaders: responseHeaders })
  })
}

const getCookies: IpcGetCookies = async (_, config) => {
  return await session.defaultSession.cookies.get(config)
}

export default function () {
  ipcMain.handle('axios', customAxios)
  ipcMain.handle('getUrlFileBuffer', getUrlFileBuffer)
  ipcMain.handle('getCacheFileBuffer', getCacheFileBuffer)
  ipcMain.handle('getCookies', getCookies)

  updateRequestHeaders()
}
